package watcher

import (
    "time"
    "fmt"
    "strings"
    "os/user"
    "../pb"
)


type SingleProcess struct {
    pid       int
    ctime     int64
    checkTime int64
    user      user.User
}

func (sp *SingleProcess) Uptime() (int64) {
    return time.Now().Unix() - sp.ctime
}
func (sp *SingleProcess) Info(b bool) string {
    t := time.Now().Unix()
    if sp.pid == 0 {
        if !b {
            return fmt.Sprintf("\tstatus: exited")
        }
        return fmt.Sprintf("\tstatus: exited, check: %d (seconds) ago",
            t-sp.checkTime)
    }
    if !b {
        return fmt.Sprintf("\tstatus: running")
    }
    return fmt.Sprintf("\tstatus: running, created: %d (seconds) ago , check: %d (seconds) ago",
        t-sp.ctime, t-sp.checkTime)
}
func (sp *SingleProcess) Status() (*pb.Status, error) {
    stat, err := GetStatus(sp.pid)
    sp.checkTime = time.Now().Unix()
    stat.ProcType="Single"
    return stat, err
}

func (sp *SingleProcess) Add(uname user.User, ctime int64, pid int) (err error) {
    if sp.pid == 0 {
        sp.pid = pid
        sp.user = uname
        sp.ctime = ctime
        sp.checkTime = time.Now().Unix()
        return
    }
    return fmt.Errorf("Duplicate Process Matched In Single define")
}

type MultiProcess struct {
    processes []*SingleProcess
}

func (sp *MultiProcess) Uptime() int64 {
    var sum int64
    var count int
    for _, v := range sp.processes {
        count += 1
        sum += time.Now().Unix() - v.ctime
    }
    return sum / int64(count)
}

func (sp *MultiProcess) Add(uname user.User, ctime int64, pid int) error {
    p := &SingleProcess{}
    if err := p.Add(uname, ctime, pid); err != nil {
        return err
    }
    sp.processes = append(sp.processes, p)
    return nil
}
func (sp *MultiProcess) Info(b bool) string {
    var s []string
    if len(sp.processes) == 0 {
        return fmt.Sprintf("\tstatus: none,")
    }
    for i, p := range sp.processes {
        s = append(s, fmt.Sprintf("\t%d%s", i, p.Info(b)))
    }
    return strings.Join(s, "\n")
}
func (sp *MultiProcess) Status() (*pb.Status, error) {
    stat := &pb.Status{}
    for _, p := range sp.processes {
        s, err := p.Status()
        if err != nil {
            return nil, err
        }
        if !IsNull(s){
            Addto(stat,s)
        }
    }
    stat.ProcType="Multi"
    return stat, nil
}

